/*
 * Created by kopper on 01.02.15 08:49
 * (C) Copyright 2015 kopperek@gmail.com
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser General Public License
 * (LGPL) version 2.1 which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/lgpl-2.1.html
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 */

package app.android.kopper.gpxdownloader.reader;

import android.hardware.usb.UsbDeviceConnection;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.util.Arrays;

import app.android.kopper.gpxdownloader.IDataReader;
import app.android.kopper.gpxdownloader.IUtilProvider;
import app.android.kopper.gpxdownloader.ProgressParam;
import app.android.kopper.gpxdownloader.R;
import app.android.kopper.gpxdownloader.UsbDevice;
import app.android.kopper.gpxdownloader.parser.MG650Parser;


public class MG650Reader implements IDataReader {

    private static final byte[] REQUEST_DEVICE_STATUS_AND_LOG_SIZE={'$','3',0x0d,0x0a};
    private static final byte[] SWITCH_TO_DOWNLOAD_MODE={'$','1',0x0d,0x0a};
    private static final byte[] REQUEST_THE_FIRST_CHUNK={0x15};
    private static final byte[] REQUEST_THE_NEXT_CHUNK={0x06};

    public static final byte[] FINISH_CONTENT={0x04,'$','F','I','N','I','S','H',0x0d,0x0a};


    @Override
    public String performReading(UsbDevice usbDevice,UsbDeviceConnection connection,IUtilProvider utils) throws IOException {

        utils.publishProgress(new ProgressParam(utils.getString(R.string.progress_checking_size),"",0,0));
        usbDevice.send(connection,REQUEST_DEVICE_STATUS_AND_LOG_SIZE);
        byte[] result=usbDevice.receiveFully(connection,10,utils); //note: 'ok' check
        BigInteger size=new BigInteger(Arrays.copyOfRange(result,6,10));

        utils.publishProgress(new ProgressParam(utils.getString(R.string.progress_switching_to_download_mode),"",0,0));
        usbDevice.send(connection,SWITCH_TO_DOWNLOAD_MODE);
        usbDevice.receiveFully(connection,6,utils); //note: 'ok' check

        File rawFile=utils.createFile("import.raw");
        FileOutputStream fos=new FileOutputStream(rawFile);

        utils.publishProgress(new ProgressParam(utils.getString(R.string.progress_reading),"0/"+size,0,0));
        usbDevice.send(connection,REQUEST_THE_FIRST_CHUNK);
        long received=0;
        for(;;) {
            byte[] buffer=new byte[1024];
            int resultSize=usbDevice.receive(connection,buffer);
            if(Arrays.equals(Arrays.copyOf(buffer,resultSize),FINISH_CONTENT))
                break;
            //it's not over yet
            if(resultSize<3)
                throw new IOException(utils.getString(R.string.error_communication_result_size));
            fos.write(buffer,3,resultSize-3);
            byte[] contentPartTwo=usbDevice.receiveFully(connection,132-resultSize,utils);
            fos.write(contentPartTwo,0,132-resultSize-1);
            //note: crc check (?)
            received+=128;
            utils.publishProgress(new ProgressParam(utils.getString(R.string.progress_reading),received+"/"+size,(int)received,size.intValue()));
            usbDevice.send(connection,REQUEST_THE_NEXT_CHUNK);
            //132 -> 128
        }
        fos.close();

        utils.publishProgress(new ProgressParam(utils.getString(R.string.progress_parsing),"",0,0));
        new MG650Parser(rawFile,received).parse(utils);
        utils.publishProgress(new ProgressParam(utils.getString(R.string.progress_done),"",0,0));

        return (null);
    }
}
